#include "air32f10x_conf.h"
#include "dac1.h"
#include "sys.h"
#include "w25qxx.h"
#include "led.h"
#include "tim2.h"

uint32_t list[LIST_MAX_LEN][2] = {0}; // 声音的地址和长度列表
uint32_t sound_list_len = 0;          // 音频列表长度
uint32_t free_addr = 0;               // flash中的空闲地址
uint32_t music_addr = 0;              // 声音在flash中地址
uint32_t music_len = 0;               // 声音长度
volatile uint8_t new_play_task = 0;   // 新播放任务
volatile uint8_t last_task_done = 1;  // 上一个任务播放完成
uint8_t music_buf[READ_N_BYTES + 6];  // 读取数据用到的缓冲区

void dac1_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void dac1_init(void)
{
    DAC_InitTypeDef DAC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);                              // 使能DAC时钟
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;                  // DAC波形生成模式:无
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;                                // 触发模式:无,写入寄存器就转换
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;                             // 触发模式:T2
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095; // 三角波取样幅度为4095
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;                   // DAC输出缓冲使能,打开缓冲会有点噪音
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);                                     // 根据DAC_InitStruct中指定的参数初始化DAC寄存器
    DAC_Cmd(DAC_Channel_1, ENABLE);                                                  // 使能DAC通道1
    *(uint8_t *)(DAC_BASE + 0x10) = 0;                                               // 输出为0
    DAC_DMACmd(DAC_Channel_1, ENABLE);                                               // DAC通道1 DMA使能
}

void dac1_dma_init(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);                      // 使能DMA时钟
    DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_BASE + 0x10;             // DAC1的DHR8R1寄存器地址
    DMA_InitStructure.DMA_MemoryBaseAddr = 0;                               // DMA的内存地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                      // DMA传输方向：内存到外设
    DMA_InitStructure.DMA_BufferSize = 0;                                   // DMA的DMA_BufferSize大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址寄存器不变
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 // 内存地址寄存器递增
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度为8位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         // 内存数据宽度为8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           // 工作在普通模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Low;                      // DMA的优先级为高
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 非内存到内存传输
    DMA_Init(DMA2_Channel3, &DMA_InitStructure);                            // 根据DMA_InitStruct中指定的参数初始化DMA的通道3
}

void dac1_read_flash_sound_list()
{
    uint32_t addr = 8;
    flash_read_data(0, (uint8_t *)&sound_list_len, 4);                 // 文件数量
    flash_read_data(4, (uint8_t *)&free_addr, 4);                      // 最后文件地址
    if (sound_list_len > LIST_MAX_LEN || free_addr >= W25Qxx_MAX_ADDR) // 校验
    {
        return;
    }
    for (uint8_t i = 0; i < sound_list_len; i++)
    {
        flash_read_data(addr, (uint8_t *)list[i], 8); // 从flash中读取列表
        addr += 8;
    }
}

void dac1_play(uint32_t flash_addr, uint32_t size, uint8_t wait)
{
    music_addr = flash_addr;
    music_len = size;
    last_task_done = 0;
    new_play_task = 1;
    if (wait)
    {
        while (last_task_done == 0)
        {
        }
    }
}

void dac1_play_digit(uint16_t n)
{
    uint16_t a = 10000;
    while (1)
    {
        if ((n / a != 0) || (a == 0))
        {
            break;
        }
        a /= 10;
    }
    if (a == 0)
    {
        dac1_play_by_index(SND_ZERO, 1);
        return;
    }
    while (a != 0)
    {
        dac1_play_by_index(SND_ZERO + n / a, 1);
        n %= a;
        a /= 10;
    }
}

void dac1_play_by_index(uint32_t index, uint8_t wait)
{
    dac1_play(list[index][0], list[index][1], wait);
    Delay_ms(1);
}

void dac1_play_n_ms_by_index(uint32_t index, uint32_t n_ms, uint8_t wait)
{
    uint32_t need_bytes = n_ms * SAMPLE_FREQUENCY / 1000;
    need_bytes = need_bytes <= list[index][1] ? need_bytes : list[index][1];
    dac1_play(list[index][0], need_bytes, wait);
}

void dac1_continue_play_sound()
{
    // 让播放不要打扰发送
    if (new_play_task == 1 || (DMA2->ISR & DMA2_FLAG_TC3))
    {
        // 清除 new play task 标志
        if (new_play_task == 1)
        {
            new_play_task = 0;
        }
        // 清DMA完成标志
        DMA2->IFCR = DMA2_FLAG_TC3;
        // 关闭通道
        DMA2_Channel3->CCR &= (uint16_t)(~DMA_CCR1_EN);
        // 读取音乐
        if (music_len >= READ_N_BYTES)
        {
            flash_read_data_via_dma(music_addr, music_buf, READ_N_BYTES);
            while (FLASH_CS == 0)
            {
            }
            DMA2_Channel3->CMAR = (uint32_t)(music_buf + 6);
            DMA2_Channel3->CNDTR = READ_N_BYTES;
            music_addr += READ_N_BYTES;
            music_len -= READ_N_BYTES;
            DMA2_Channel3->CCR |= DMA_CCR1_EN;
        }
        else if (music_len > 0)
        {
            flash_read_data_via_dma(music_addr, music_buf, music_len);
            while (FLASH_CS == 0)
            {
            }
            DMA2_Channel3->CMAR = (uint32_t)(music_buf + 6);
            DMA2_Channel3->CNDTR = music_len;
            music_addr = music_len = 0;
            DMA2_Channel3->CCR |= DMA_CCR1_EN;
        }
        else
        {
            last_task_done = 1;
        }
    }
}

void speak_time(uint32_t time_of_10ms)
{
    dac1_play_digit(time_of_10ms / 100);
    Delay_ms(50);
    dac1_play_by_index(SND_POINT, 1);
    Delay_ms(50);
    dac1_play_digit(time_of_10ms % 100 / 10);
    Delay_ms(50);
    dac1_play_digit(time_of_10ms % 100 % 10);
    Delay_ms(50);
    dac1_play_by_index(SND_SECOND, 1);
    Delay_ms(50);
}